#pragma once
#include <iostream>
#include <pthread.h>
#include <functional>
#include "Sock.hpp"
#include "Protocol.hpp"

namespace tcp_server
{
    using namespace Protocol_ns;

    using func_t = std::function<Response(const Request &)>;

    class TcpServer;

    class ThreadData
    {
    public:
        ThreadData(int sock, std::string ip, uint16_t port, TcpServer *p)
            : _sock(sock), _ip(ip), _port(port), _tsvrp(p)
        {
        }
        ~ThreadData()
        {
        }

    public:
        int _sock;
        std::string _ip;
        uint16_t _port;
        TcpServer *_tsvrp;
    };

    class TcpServer
    {
    public:
        TcpServer(func_t func, uint16_t port)
            : _func(func), _port(port)
        {
        }

        void InitServer()
        {
            _listensock.Socket();
            _listensock.Bind(_port);
            _listensock.Listen();
            logMessage(Info, "Init server success,listensock:%d", _listensock.Fd());
        }

        void Start()
        {
            while (true)
            {
                std::string clientip;
                uint16_t clientport;
                int sock = _listensock.Accept(&clientip, &clientport);
                if (sock < 0)
                {
                    continue;
                }
                logMessage(Debug, "git a new client, client inof:[%s:%d]", clientip.c_str(), clientport);

                pthread_t tid;
                ThreadData *td = new ThreadData(sock, clientip, clientport, this);
                pthread_create(&tid, nullptr, ThreadRoutine, td);
            }
        }

        // 这个函数被多线程调用
        void ServiceIO(int sock, const std::string &ip, const uint16_t &port)
        {
            logMessage(Debug, "ServiceIO调用成功");
            std::string inbuffer;
            while (true)
            {
                // 读取数据——无法保证读取到的是完整的报文，所以循环读取，边读取，边检测
                std::string package;
                int n = ReadPackage(sock, inbuffer, &package);
                if (n == -1)
                {
                    break;
                }
                else if (n == 0)
                {
                    continue;
                }
                else
                {
                    logMessage(Debug, "服务器端：数据接收成功");

                    // 去掉报头
                    package = RemoveHeader(package, n);
                    logMessage(Debug, "服务器端：去报头成功");


                    // 反序列化提取数据：string -> struct
                    Request req;
                    req.Deserialize(package);
                    logMessage(Debug, "服务器端：反序列化成功");


                    // 处理提取到的数据——业务处理
                    Response resp = _func(req); // 回调函数
                    logMessage(Debug, "服务器端：数据计算成功");


                    // 序列化准备发送数据：struct -> string
                    std::string send_string;
                    resp.Serialize(&send_string);
                    logMessage(Debug, "服务器端：序列化成功");

                    // 添加报头
                    send_string = AddHeader(send_string);
                    logMessage(Debug, "服务器端：添加报头成功");


                    // 发送序列化数据到网络
                    send(sock, send_string.c_str(), send_string.size(), 0);
                    logMessage(Debug, "服务器端：数据发送成功");
                }
            }
            close(sock);
        }

        static void *ThreadRoutine(void *argv)
        {
            pthread_detach(pthread_self());
            ThreadData *td = static_cast<ThreadData *>(argv);

            // logMessage(Debug, "thread running");
            td->_tsvrp->ServiceIO(td->_sock, td->_ip, td->_port);
            delete td;
            return nullptr;
        }

        ~TcpServer()
        {
            _listensock.Close();
        }

    private:
        uint16_t _port;
        Sock _listensock;
        func_t _func;
    };
}